package com.outsider.weixin.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.crypto.dsig.keyinfo.RetrievalMethod;

import org.eclipse.jetty.util.UrlEncoded;

import com.jfinal.kit.PropKit;
import com.jfinal.log.Log;
import com.jfinal.weixin.demo.WeixinMsgController;
import com.jfinal.weixin.sdk.api.AccessToken;
import com.jfinal.weixin.sdk.api.AccessTokenApi;
import com.jfinal.weixin.sdk.api.ApiResult;
import com.jfinal.weixin.sdk.api.CustomServiceApi;
import com.jfinal.weixin.sdk.api.UserApi;
import com.jfinal.weixin.sdk.msg.in.InLocationMsg;
import com.jfinal.weixin.sdk.msg.in.InTextMsg;
import com.jfinal.weixin.sdk.msg.in.InVoiceMsg;
import com.jfinal.weixin.sdk.msg.in.event.InFollowEvent;
import com.jfinal.weixin.sdk.msg.in.event.InLocationEvent;
import com.jfinal.weixin.sdk.msg.in.event.InMenuEvent;
import com.jfinal.weixin.sdk.msg.out.OutNewsMsg;
import com.jfinal.weixin.sdk.msg.out.OutTextMsg;
import com.jfinal.weixin.sdk.session.WxSession;
import com.outsider.movie.dao.Movie;
import com.outsider.news.dao.Acfun;
import com.outsider.news.dao.BaseNews;
import com.outsider.news.dao.Keyword;
import com.outsider.news.dao.Zhihu;
import com.outsider.news.service.NewsService;
import com.outsider.note.dao.TextNote;
import com.outsider.note.dao.VoiceNote;
import com.outsider.note.service.TextNoteService;
import com.outsider.note.service.VoiceNoteService;
import com.outsider.product.dao.Product;
import com.outsider.product.dao.ProductRecord;
import com.outsider.product.service.ProductService;
import com.outsider.thunder.dao.TaskBase;
import com.outsider.thunder.service.ThunderService;
import com.outsider.util.Const;
import com.outsider.util.DailyReport;
import com.outsider.util.RegularExpression;
import com.outsider.util.ZhiHuUtil;
import com.outsider.util.baiduMap.Address;
import com.outsider.util.baiduMap.BaiduMapApi;
import com.outsider.util.thunder.Thunder;
import com.outsider.util.weather.SimpleWeather;
import com.outsider.util.weather.WeatherApi;
import com.outsider.weixin.dao.Location;
import com.outsider.weixin.dao.User;

public class MyMsgController extends WeixinMsgController {
	private VoiceNoteService voiceNoteService = new VoiceNoteService();
	private TextNoteService textNoteService = new TextNoteService();
	private ThunderService thunderService = new ThunderService();
	private ProductService productService = new ProductService();
	private NewsService newsService = new NewsService();

	@Override
	protected void processInTextMsg(InTextMsg inTextMsg) {
		String msgContent = inTextMsg.getContent().trim();

		if (msgContent.startsWith(Const.TEXT_NOTE_MARK)) {
			textNoteService.saveTextNote(msgContent, inTextMsg.getFromUserName());
			OutTextMsg otm = new OutTextMsg(inTextMsg);
			otm.setContent("Note添加成功");
			render(otm);
		} else if (msgContent.startsWith(Const.VOICE_NOTE_MARK)) {
			String msg[] = msgContent.split(" ", 3);
			Date date = null;
			try {
				date = Const.SDF.parse(msg[1] + " " + msg[2]);
			} catch (ParseException e) {
				e.printStackTrace();
			}
			WxSession ws = getWxSession();
			ws.setAttribute(Const.FLAG, Const.VOICE_NOTE_MARK);
			ws.setAttribute(Const.DATE, date);
			OutTextMsg otm = new OutTextMsg(inTextMsg);
			otm.setContent("请发送语音Note");
			render(otm);
		} else if (RegularExpression.urlTest(msgContent) || msgContent.startsWith(Const.THUNDER_LINK_START)
				|| msgContent.startsWith(Const.MAGNET_LINK_START) || msgContent.startsWith(Const.EMULE_LINK_START)) {
			renderNull();
			String openID = inTextMsg.getFromUserName();
			addTask(msgContent, openID);
			return;
		} else if(msgContent.startsWith(Const.MOVIE_MARK)){
		    String title=msgContent.split(" ")[1];
		    List<Movie> list=Movie.dao.findMovieByTitle(title);
		    StringBuilder sb=new StringBuilder();
		    if (null==list||list.isEmpty()){
		    	sb.append("没有找到标题为\""+msgContent+"\"的电影,可能尚未收录.");
		    }
		    else{
		    	sb.append(Movie.dao.buildString(list,inTextMsg.getFromUserName()));
		    }
			OutTextMsg otm = new OutTextMsg(inTextMsg);
			otm.setContent(sb.toString());
			render(otm);
		}else if (Const.KEYWORD == getWxSession().getAttribute(Const.STATUS)) {
			User user = User.dao.findByOpenID(inTextMsg.getFromUserName());
			OutTextMsg otm = new OutTextMsg(inTextMsg);
			// 输入end
			if (msgContent.equals(Const.END)) {
				getWxSession().removeAttribute(Const.STATUS);
				otm.setContent("您的keyWord已更新");
			}
			// 输入编号 删除keyword
			else if (msgContent.length() == 1 && RegularExpression.isInteger(msgContent)) {
				Keyword.dao.deleteKeyword(user.getID(), Integer.parseInt(msgContent));
				otm.setContent(Keyword.dao.showKeyword(user.getID()));
			}
			// 新增keyword 去重后优先去除排位靠前的keyword
			else {
				String[] newKeyWords = msgContent.trim().split(" ");
				Keyword.dao.addNewKeyword(user.getID(), newKeyWords);
				otm.setContent(Keyword.dao.showKeyword(user.getID()));
			}
			render(otm);
		} else {
			OutNewsMsg onm = new OutNewsMsg(inTextMsg);
			List<Zhihu> zhihuList = Zhihu.dao.findRandomNews(4, null);
			zhihuList.forEach(zhihu -> {
				onm.addNews(zhihu.getTitle(), null, zhihu.getImages(), ZhiHuUtil.NEWS_URL + zhihu.getID());
			});
			render(onm);
		}
	}

	private void addTask(String url, String openID) {
		Thread thread=new Thread(new Runnable() {
			@Override
			public void run() {
				 Integer bo=thunderService.addThunderTask(url,openID);	 
				 String msg;
				 if (bo==Const.THUNDER_TASK_ADD_EXIST) return;
				 if (bo==Const.THUNDER_TASK_ADD_SUCCESS) msg="新增链接任务成功";
				 else msg="新增链接任务失败";
				 CustomServiceApi.sendText(openID, msg);
			}
		});
		thread.start();
	}

	@Override
	protected void processInVoiceMsg(InVoiceMsg inVoiceMsg) {
		if (Const.VOICE_NOTE_MARK.equals(getWxSession().getAttribute(Const.FLAG))) {
			// 临时语音消息保存3天 语音提醒时间在三天内的保存ID 三天外的将语音保存在本地
			Calendar temp = Calendar.getInstance();
			temp.add(Calendar.DAY_OF_YEAR, 3);
			Date lineDate = temp.getTime();
			Date callDate = (Date) getWxSession().getAttribute(Const.DATE);
			String openID = inVoiceMsg.getFromUserName();

			// 提醒时间在3天之后
			if (callDate.after(lineDate))
				voiceNoteService.longTimeNoteSave(inVoiceMsg, callDate, openID);
			else
				voiceNoteService.shortTimeNoteSave(inVoiceMsg, callDate, openID);
			OutTextMsg otm = new OutTextMsg(inVoiceMsg);
			otm.setContent("语音Note接受成功");
			render(otm);
		} else {
			OutTextMsg otm = new OutTextMsg(inVoiceMsg);
			otm.setContent("无法解析");
			render(otm);
		}
	}

	protected void processInMenuEvent(InMenuEvent inMenuEvent) {
		String key = inMenuEvent.getEventKey();
		OutTextMsg outMsg = new OutTextMsg(inMenuEvent);
		StringBuilder sb = new StringBuilder();
		// 迅雷模块——最近10个任务
		if (key.equals(Const.THUNDER_LAST10_EVENT_KEY)) {
			List<TaskBase> list = thunderService.findLast10Task(inMenuEvent.getFromUserName());
			list.forEach(taskBase -> {
				Long nowSize = Long.parseLong(taskBase.getTotalReceiveValidSize());
				Long totSize = Long.parseLong(taskBase.getResourceSize());
				Long rate = 0L;
				if (totSize != 0)
					rate = (nowSize * 100) / totSize;
				Integer intRate = rate.intValue();
				if (taskBase.getStatus() == 8 || taskBase.getStatus() == 10)
					intRate = 100;
				sb.append(taskBase.getName().trim() + " " + intRate + "% \n");
			});
		}
		// watch Dog模块——当前价格
		else if (key.equals(Const.PRODUCT_WATCH_DOG_SHOW)) {
			List<ProductRecord> list = productService.getLatestRecord(inMenuEvent.getFromUserName());
			list.forEach(productRecord -> {
				int productID = productRecord.getProductId();
				Product product = Product.dao.findById(productID);
				String name = product.getNAME();
				Double minPrice = Double.MAX_VALUE;
				String url = null;
				if (productRecord.getAmPrice() != null && productRecord.getAmPrice().doubleValue() < minPrice) {
					url = product.getAMURL();
					minPrice = productRecord.getAmPrice().doubleValue();
				}
				if (productRecord.getJdPrice() != null && productRecord.getJdPrice().doubleValue() < minPrice) {
					url = product.getJDURL();
					minPrice = productRecord.getJdPrice().doubleValue();
				}
				if (productRecord.getDdPrice() != null && productRecord.getDdPrice().doubleValue() < minPrice) {
					url = product.getDDURL();
					minPrice = productRecord.getDdPrice().doubleValue();
				}
				sb.append(name + "  " + minPrice + "¥  " + url + "\n");
			});
		}
		// watch Dog模块——刷新价格
		else if (key.equals(Const.PRODUCT_WATCH_DOG_UPDATE)) {
			renderOutTextMsg("价格更新中 请稍后");
			// 超过微信平台5s回复限制 主进程回复等待消息 用副进程进行更新操作
			Thread thread = new Thread(new Runnable() {
				@Override
				public void run() {
					boolean flag = productService.updateRecord(inMenuEvent.getFromUserName());
					if (flag)
						sb.append("更新记录成功");
					else
						sb.append("更新记录失败,请查看日志");
					// 更新完成后调用客服回复接口
					CustomServiceApi.sendText(inMenuEvent.getFromUserName(), sb.toString());
				}
			});
			thread.start();
			return;
		}
		// Note模块——Daily Report
		else if (key.equals(Const.DAILY_REPORT)) {
			User user = User.dao.findByOpenID(inMenuEvent.getFromUserName());
			Location location = Location.dao.findLocationByUserID(user.getID());
			Address address = BaiduMapApi.getAddress(location.getLongitude().toString(),
					location.getLatitude().toString());

			SimpleWeather simpleWeather = (SimpleWeather) getWxSession().getAttribute("weatherData");
			if (simpleWeather == null) {
				simpleWeather = WeatherApi.getTodayWeather(location.getLongitude().toString(),
						location.getLatitude().toString());
				getWxSession().setAttribute("weatherData", simpleWeather);
			}

			List<TextNote> textNoteList = TextNote.dao.findTodayNote();
			List<VoiceNote> voiceNoteList = VoiceNote.dao.findTodayNote();
			List<Movie> movieList = Movie.dao.findLatestMovie();

			sb.append(DailyReport.GeneratorWelcomeMessage());
			sb.append("," + user.getNAME() + "\r\n");
			if (simpleWeather != null) {
				sb.append("今日" + address.getProvince() + address.getCity() + address.getDistrict() + "\r\n");
				sb.append("白天:" + simpleWeather.getDay_weather() + " 气温:" + simpleWeather.getDay_air_temperature()
						+ "\r\n");
				sb.append("夜晚:" + simpleWeather.getNight_weather() + " 气温:" + simpleWeather.getNight_air_temperature()
						+ "\r\n");
				sb.append("<a href=\""+PropKit.get("website")+"/weather/detail.html?openID="+user.getOpenId()+"\">点击查看更多</a>\r\n");
			}
			if (null == textNoteList || textNoteList.size() == 0) {
				sb.append("今日您有0条TextNote" + "\r\n");
			} else {
				sb.append("今日您有" + textNoteList.size() + "条TextNote" + "\r\n");
				textNoteList.forEach(textNote -> {
					sb.append(Const.SDF.format(textNote.getDATE()) + " " + textNote.getMSG() + "\r\n");
				});
			}
			if (null == voiceNoteList || voiceNoteList.size() == 0) {
				sb.append("今日您有0条VoiceNote" + "\r\n");
			} else {
				sb.append("今日您有" + voiceNoteList.size() + "条TextNote" + "\r\n");
			}
			if (null == movieList || movieList.size() == 0)
				sb.append("今日没有电影更新TAT\r\n");
			else {
				sb.append("今天更新了" + movieList.size() + "部电影\r\n");
				sb.append(Movie.dao.buildString(movieList,inMenuEvent.getFromUserName()));
			}

		}
		// news模块 keyword管理
		else if (key.equals(Const.NEWS_KEYWORD)) {
			User user = User.dao.findByOpenID(inMenuEvent.getFromUserName());
			sb.append(Keyword.dao.showKeyword(user.getID()));
			getWxSession().setAttribute(Const.STATUS, Const.KEYWORD);
		}
		// news模块 知乎 acfun 凤凰
		else if (key.equals(Const.ZHIHU_NEWS) || key.equals(Const.ACFUN_NEWS) || key.equals(Const.PHOENIX_NEWS)) {

			Set<BaseNews> set = (Set<BaseNews>) getWxSession().getAttribute(key);
			User user = User.dao.findByOpenID(inMenuEvent.getFromUserName());
			if (set == null) {
				set = new HashSet<BaseNews>();
				getWxSession().setAttribute(key, set);
			}
			List<BaseNews> list = newsService.getNews(user.getID(), set, key);

			OutNewsMsg onm = new OutNewsMsg(inMenuEvent);
			list.forEach(zhihu -> {
				onm.addNews(zhihu.getNews());
			});
			render(onm);
			return;
		}
		String str = sb.toString();
		outMsg.setContent(str);
		render(outMsg);
	}

	@Override
	protected void processInFollowEvent(InFollowEvent inFollowEvent) {
		if (InFollowEvent.EVENT_INFOLLOW_SUBSCRIBE.equals(inFollowEvent.getEvent())) {
			Log.getLog("").info("关注：" + inFollowEvent.getFromUserName());
			// 写入User表
			User user = new User();
			user.setNAME(UserApi.getUserInfo(inFollowEvent.getFromUserName()).getStr("nickname"));
			user.setOpenId(inFollowEvent.getFromUserName());
			user.save();
			OutTextMsg outMsg = new OutTextMsg(inFollowEvent);
			outMsg.setContent("欢迎使用OutSider个人助理\r\n江湖自古多歧路\r\n人间至此燕无书");
			render(outMsg);
		}
		// 如果为取消关注事件，将无法接收到传回的信息
		if (InFollowEvent.EVENT_INFOLLOW_UNSUBSCRIBE.equals(inFollowEvent.getEvent())) {
			Log.getLog("").info("取消关注：" + inFollowEvent.getFromUserName());
			User.dao.deleteById(User.dao.findIDbyOpenID(inFollowEvent.getFromUserName()));
			renderNull();
		}
	}

	@Override
	protected void processInLocationEvent(InLocationEvent inLocationEvent) {
		Integer userID = User.dao.findIDbyOpenID(inLocationEvent.getFromUserName());
		Location.dao.save(userID, inLocationEvent.getLongitude(), inLocationEvent.getLatitude());
		renderNull();
	}

}
